<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\index\service;

use app\index\model\Agent;
use app\index\model\CommissionAssessment;
use app\index\model\Commodity;
use app\index\model\Configuration;
use app\index\model\MembershipLevel;
use app\index\model\Order;
use app\index\model\Sku;
use app\index\model\SkuInventory;
use app\index\model\User;
use app\index\util\Redis;
use app\madmin\model\AgentGrade;
use app\utils\RedisUtil;
use think\Exception;
use think\facade\Db;

class CommissionService
{
    private $redis;
    private $tree = [];
    private $agent = null;

    public function __construct()
    {
        global $user;
        $this->user = User::find($user['id']);
        if (!empty($this->user))
            $this->user = $this->user->toArray();
        $this->redis = new RedisUtil();
    }

    /**
     * 更新数组指针为等级
     * @param $data array 排序数据
     * @param $is_level boolean 是否系统等级
     * @param $level int 层级
     * @return mixed
     */
    private function sort($data, $is_level = true, $level = 3)
    {
        $arr = [];
        foreach ($data as $key => $value) {
            if ($key < $level) {
                if ($is_level) {
                    $arr[$value['level']] = $value;
                } else {
                    $arr[$value[0][0]] = $value;
                }
            }
        }
        return $arr;
    }

    /**
     * 获取层级下的分销商
     * @param int|null $pid 用户上级
     * @param $l int 分销层级
     * @throws
     */
    private function getAgent($pid, $l)
    {
        if (empty($pid)) return;
        $this->agent = Agent::with([
            'superior' => function ($query) {
                $query->with(['superior']);
            }])
            ->field('id,user_id,name,pid,grade_id')
            ->where('id', $pid)
            ->find();
        if (!empty($this->agent)) {
            $this->agent = $this->agent->toArray();
            $i = 1;
            $superiors = $this->agent;
            while (!empty($superiors)) {
                $superiors['level'] = $i;
                $this->tree[] = $superiors['id'];
                $tump = $superiors;
                if (!empty($tump['superior'])) {
                    $i++;
                    unset($tump['superior']);
                    $superiors = $superiors['superior'];
                } else {
                    $superiors = null;
                }
                $all[] = $tump;
            }
            $all = $this->sort($all, true, $l);
            $this->agent = $all;
        } else {
            $this->agent = null;
        }
    }

    private function getItems($order)
    {
        $items = $order->orderCommodity;
        if ($order['coupon_money'] == 0) {
            return $items;
        }
        $coupon_money = $order['coupon_money'];
        foreach ($items as $key => $value) {
            if (count($items) -1 == $key) {
                $items[$key]['money'] = $value['money'] - sprintf("%.2f", substr(sprintf("%.3f", $coupon_money), 0, -2));
            } else {
                $coupon = ($value['money'] / $order['money']) * $order['coupon_money'];
                $items[$key]['money'] = $value['money'] - sprintf("%.2f", substr(sprintf("%.3f", $coupon), 0, -2));
                $coupon_money -= $coupon;
            }
        }
        return $items;
    }

    public function getAgentMoney(Order $order, int $pid = 0)
    {


        $user = $this->user;
        $time = date("Y-m-d H:i:s", time());
        $where = [
            ['start_time', '<', $time],
            ['end_time', '>', $time],
            ['status', 'in', [0, 1]],
            ['mall_id', '=', $user['mall_id']]
        ];

        #考核活动
        $assessment = CommissionAssessment::where($where)->find();

        $agent = Agent::where('user_id', $user['id'])->find();
        $config = Configuration::where('type', 'agentExplain')->where('mall_id', $user['mall_id'])->value('configuration');
        $config = json_decode($config, true);
        // 空配置||不是分销商并参与内购
        if (empty($config) || (empty($agent) && $config['inPurchasing'] == 1)) return;
        if (empty($user['pid']) && $config['relationship'] == 1) {
            $this->redis->set('pid-' . $user['id'], $pid, 36000);
        } else {
            $pid = $user['pid'];
        }
        $xlevel = $config['level'];
        $this->getAgent($pid, $xlevel);
        $inPurchasing = $config['inPurchasing'];
        $orderCommodities = $this->getItems($order);
        foreach ($orderCommodities AS $key => $value) {
            $commodity = $this->redis->get(checkRedisKey("COMMODITY:" . $value['commodity_id']));
            if (empty($commodity)) continue;
            $commodity = json_decode($commodity, true);
            // 是否参与分销
            if ($commodity['is_distribution'] == 0) continue;

            $distribution = $commodity['distribution'];
            // 跟随系统设置
            if ($commodity['is_base_distribution'] == 0) {
                global $mid;
                // 分销层级
                $level = $config['level'];
                // 分销比例
                $distribution = $config['profit'];

                $array = [];
                $keyword = [1 => 'first', 2 => 'second', 3 => 'third'];
                if ($agent['pid'] > 0) {
                    $p_agent = Agent::with('grade')->find($agent['pid']);
                    if (!empty($p_agent) && $p_agent['pid'] > 0) {
                        $pp_agent = Agent::with('grade')->find($p_agent['pid']);
                        if (!empty($pp_agent) && $pp_agent['pid'] > 0) {
                            $ppp_agent = Agent::with('grade')->find($pp_agent['pid']);
                        }
                    }
                }
                for ($i = 1; $i < 4; $i++) {
                    $temp = ['type' => 0, 'figure' => $distribution[$keyword[$i]], 'level' => $i];
                    if ($inPurchasing != 1) {
                        switch ($i) {
                            case 1:
                                $temp['figure'] = isset($p_agent['grade']) ? $p_agent['grade']['l1'] : $distribution[$keyword[$i]];
                                break;
                            case 2:
                                $temp['figure'] = isset($pp_agent['grade']) ? $pp_agent['grade']['l2'] : $distribution[$keyword[$i]];
                                break;
                            case 3:
                                $temp['figure'] = isset($ppp_agent['grade']) ? $ppp_agent['grade']['l2'] : $distribution[$keyword[$i]];
                        }
                    }
                    if (!empty($level) && $level < $i) {
                        $temp['figure'] = 0;
                    }
                    $array[] = $temp;
                }
                $distribution = $this->sort($array, true, $xlevel);
            }
            if (empty($distribution)) continue;
            $tump = [];
            if (!is_array($distribution)) {
                $distribution = json_decode($distribution, true);
            }
            foreach ($distribution AS $index => $item) {
                if (isset($item['level'])) {
                    $tump[$item['level']] = $item;
                }
            }
            $money=[];
            // 原标准执行
            if (!empty($tump)) {
                for ($i = 1; $i < $xlevel; $i++) {
                    if ($tump[$item['level']]['type'] == 0) {
                        $sum = $value['money'];
                        $figure = bcmul(0.01, $item['figure'], 4);
                        $money[] = bcmul($sum, $figure, 2);
                        $figure = bcmul(0.01, $tump[$i]['figure'], 4);
                        $amount = bcmul($sum, $figure, 2);
                    } else {
                        $amount = $tump[$i]['figure'];
                    }
                    $orderAgent['agent' . $i] = 0;
                    $orderAgent['amount' . $i] = $amount;
                }
            }
            $string = md5(uniqid() . rand(1000, 9999) . $key);

            //是否内购
            if ($inPurchasing == 1) {
                $string = md5(rand(1000, 9999) . uniqid() . rand(1000, 9999));
                $money = [];
                // 自设佣金
                if ($commodity['is_base_distribution']) {
                    // 新增等级
                    if (!isset($distribution[0]['type'])) {
                        $g_dis = $this->sort($distribution, false, 11);
                        if (isset($g_dis[$agent['grade_id']])) {
                            $distribution = $g_dis[$agent['grade_id']][1];
                        } else {
                            continue;
                        }
                    }
                } else {
                    if ($agent['grade_id'] > 0) {
                        $grade = AgentGrade::find($agent['grade_id'])->toArray();
                        foreach ($tump as $kt => $kv) {
                            $tump[$kt]['figure'] = $grade["l" . $kt];
                        }
                    }
                    $distribution = $tump;
                }
                if (isset($distribution[0])) {
                    $distribution = $this->sort($distribution);
                }
                $tree = $agent->id;

                $bill1=[];
                foreach ($distribution AS $index => $item) {
                    if ($item['type'] == 0) {
                        $figure = bcmul(0.01, $item['figure'], 2);
                        $gmoney[] = $item['figure'];
                        $money = bcmul($value['money'], $figure, 4);
                    } else {
                        $gmoney[] = bcmul($item['figure'], $value['count'], 2);
                        $figure = round($item['figure'] / $value['money'], 2);
                        $money = bcmul($item['figure'], $value['count'], 2);
                    }
                    $figure = (float)$figure;
                    if ($figure >= 100) {
                        $figure = 99.9999;
                    }
                    if ($index <= $xlevel) {
                        $bill_info = [
                            'amount' => $money,
                            'money' => $value['money'],
                            'tree' => $tree,
                            'source_user_id' => $user['id'],
                            'user_id' => $user['id'],
                            'mall_id' => $user['mall_id'],
                            'agent_id' => $agent->id,
                            'steps' => $index == 1 ? 0 : $index,
                            'order_id' => $order->id,
                            'order_no' => $order->order_no,
                            'commodity_id' => $value['commodity_id'],
                            'order_commodity_id' => $value['id'],
                            'sku_id' => $value['sku_id'],
                            'number' => $value['count'],
                            'figure' => $figure,
                            'figure_type' => 1,
                            'status' => 0,
                            'uniqid' => $string,
                            'create_time' => now(),
                            'update_time' => now(),
                            'commission_rate' => 0,
                            'commission' => 0,
                            'is_assessment' => 0,
                            'assessment_status' => 0,
                            'is_self' => 1 #是否自购订单
                        ];

                        #自购
                        if (!empty($assessment)) {
                            $bill_info = array_merge($bill_info, $this->getRate($assessment, $agent, $value['money']));
                        }

                        $bill[] = $bill_info;
                        $bill1[]=$bill_info;
                        $tree .= '->' . $agent->id;
                    }

                }


                $temp = [];

                foreach($bill1 as $item1=>$value1){
                    $temp['agent' . ($item1+1)] = $value1['agent_id'];
                    $temp['amount' . ($item1+1)] = $value1['amount'];
                }

//                for ($i = 1; $i <= $xlevel; $i++) {
//                    $temp['agent' . $i] = $agent->id;
//                    $temp['amount' . $i] = $gmoney[$i - 1];
//                }

                $temp['order_id'] = $order->id;
                $temp['order_no'] = $order->order_no;
                $temp['commodity_id'] = $value['commodity_id'];
                $temp['uniqid'] = $string;
                $temp['mall_id'] = $user['mall_id'];
                $orderAgentList[] = $temp;
            } else {
                if (empty($this->agent)) break;
                foreach ($this->agent AS $index => $item) {
                    if (!empty($tump)) {
                        // type0:比例，1：固定
                        if ($tump[$item['level']]['type'] == 0) {
                            $figure = bcmul(0.01, $tump[$item['level']]['figure'], 4);
                            $amount = bcmul($value['money'], $figure, 2);
                        } else {
                            $figure = round($tump[$item['level']]['figure'] / $value['money'], 2);
                            $amount = bcmul($tump[$item['level']]['figure'], $value['count'], 2);
                        }
                    } else {
                        // 新自设佣金
                        foreach ($distribution as $dkey => $dvalue) {
                            $gid = $dvalue[0][0];
                            $gcontent = $this->sort($dvalue[1], true, $xlevel);
                            // 层级匹配
                            if ($gid == $item['grade_id']) {
                                if ($gcontent[$item['level']]['type'] == 0) {
                                    $figure = bcmul(0.01, $gcontent[$item['level']]['figure'], 4);
                                    $amount = bcmul($value['money'], $figure, 2);
                                } else {
                                    $figure = round($gcontent[$item['level']]['figure'] / $value['money'], 2);
                                    $amount = bcmul($gcontent[$item['level']]['figure'], $value['count'], 2);
                                }
                            }
                        }
                    }
                    if (empty($figure)) continue;
                    $max = array_search($item['id'], $this->tree);
                    $tree = [];
                    for ($i = 0; $i <= $max; $i++)
                        $tree[] = $this->tree[$i];
                    $tree = implode('->', $tree);
                    $figure = (float)$figure;
                    if ($figure >= 100) {
                        $figure = 99.9999;
                    }
                    $bill_info = [
                        'amount' => $amount,
                        'money' => $value['money'],
                        'agent_id' => $item['id'],
                        'user_id' => $item['user_id'],
                        'mall_id' => $user['mall_id'],
                        'source_user_id' => $user['id'],
                        'tree' => $tree,
                        'steps' => $max + 1,
                        'order_no' => $order->order_no,
                        'order_id' => $order->id,
                        'commodity_id' => $value['commodity_id'],
                        'order_commodity_id' => $value['id'],
                        'sku_id' => $value['sku_id'],
                        'number' => $value['count'],
                        'figure' => $figure,
                        'figure_type' => !empty($tump) ? $tump[$max + 1]['type'] : $gcontent[$max + 1]['type'],
                        'status' => 0,
                        'uniqid' => $string,
                        'create_time' => now(),
                        'update_time' => now(),
                        'commission_rate' => 0,
                        'commission' => 0,
                        'is_assessment' => 0,
                        'assessment_status' => 0,
                        'is_self' => 0 #是否自购订单
                    ];

                    #只针对一级分销
                    if (!empty($assessment)) {
                        $bill_info = array_merge($bill_info, $this->getRate($assessment, $item, $value['money']));
                    }

                    $bill[] = $bill_info;
                    $orderAgent['agent' . ($max + 1)] = $item['id'];
                    $orderAgent['amount' . ($max + 1)] = $amount;
                }
                $orderAgent['order_id'] = $order->id;
                $orderAgent['order_no'] = $order->order_no;
                $orderAgent['mall_id'] = $user['mall_id'];
                $orderAgent['commodity_id'] = $value['commodity_id'];
                $orderAgent['uniqid'] = $string;
                $orderAgentList[] = $orderAgent;
            }
        }

        if (empty($bill)) return;

        Db::name('agent_bill_temporary')->insertAll($bill);
        Db::name('order_agent_profit')->insertAll($orderAgentList);
    }

    /**
     * 获取考核奖励中的额外的佣金
     * @param $assessment 考核详情
     * @param $agent 代理
     * @param $pay_price 实际支付金额
     * @param $assessment_value 考核金额
     * @return float|int
     */
    public function getRate($assessment, $agent, $pay_price)
    {

        $mid = $agent['mall_id'];
        #考核依据 0=分销商订单总额 1=分销订单总数
        $assessment_type = $assessment->assessment_type;
        $level_type = $assessment->level_type;

        $agent_level = $agent['grade_id'];
        $agent_where[] = ['mall_id', "=", $mid];

        if ($level_type == 1) {
            $levels = json_decode($assessment->levels, true);
            if (!empty($levels)) {
                if (!in_array($agent_level, $levels)) {
                    return ['commission_rate' => 0, 'commission' => 0, 'is_assessment' => 0, 'assessment_status' => 0];
                }
            } else {
                return ['commission_rate' => 0, 'commission' => 0, 'is_assessment' => 0, 'assessment_status' => 0];
            }
        }

//        $where = [["create_time", ">", $assessment->start_time], ["create_time", "<", $assessment->end_time], ["mall_id", '=', $assessment->mall_id], ["agent_id", '=', $agent->id]];
//
//        if ($assessment_type == 0) {
//            $assessment_value = \app\madmin\model\CommissionAssessment::getPayment($where);
//        } else {
//            $assessment_value = \app\madmin\model\CommissionAssessment::getOrderCount($where);
//        }
//
//        $role_data = json_decode($assessment->role, true);
//
//        foreach ($role_data as $role_info) {
//            if ($role_info['level'] == $agent_level) {
//                $role = $role_info['rule'];
//                $role_count = count($role);
//                for ($i = $role_count - 1; $i >= 0; $i--) {
//                    if ($assessment_value >= $role[$i]['min']) {
//                        $commission = $pay_price * number_format($role[$i]['ladder_commission_rate'] / 100, 2);
//                        return ['commission_rate' => $role[$i]['ladder_commission_rate'], 'commission' => $commission, 'is_assessment' => 1, 'assessment_status' => 0];
//                    }
//                }
//                break;
//            }
//        }

        return ['commission_rate' => 0, 'commission' => 0, 'is_assessment' => 1, 'assessment_status' => 0];
    }


    public function settlement($order): bool
    {
        if (!is_array($order)) $order->toArray();
        Db::name('agent_bill_temporary')
            ->where('order_id', $order['id'])
            ->update(['update_time' => now()]);
        return true;
    }

    public function commodityDistribution(int $commodity_id)
    {
        $commodity = json_decode($this->redis->get(checkRedisKey("COMMODITY:" . $commodity_id)), true);
        $distribution = json_decode(Configuration::where('type', 'agentExplain')->value('configuration'), true);
        if ($commodity['is_distribution'] == 1 && $distribution['open'] == 1 && $distribution['is_show_profit'] > 0 && $distribution['level'] > 0 && $this->user) {
            $agent = Agent::with("grade")->where('user_id', $this->user['id'])->find();
            $prices = $this->getPrices($commodity_id, $commodity['sell_price'], $commodity['has_sku']);
            // 1分销商
            if ($agent) {
                // 商品自设
                if ($commodity['is_base_distribution'] == 1) {
                    $distribution = is_array($commodity['distribution']) ? $commodity['distribution'] : json_decode($commodity['distribution'], true);
                    $arr = $this->getCommodityGrade($distribution, $agent['grade_id'], 1)[1];
                }
                // 系统默认
                if ($commodity['is_base_distribution'] == 0) {
                    $arr = [
                        'type' => 0,
                        'figure' => $agent['grade_id'] > 0 ? $agent['grade']['l1'] : $distribution['profit']['first']
                    ];
                }
                $return = [];
                foreach ($prices as $pk => $pv) {
                    // 1固定
                    if ($arr['type'] == 1) {
                        array_push($return, $arr['figure']);
                    }
                    // 0比例
                    if ($arr['type'] == 0) {
                        array_push($return, round($pv*$arr['figure']/100, 2));
                    }
                }
            } else {
                // 2所有人
                $agents = AgentGrade::field("id,l1,l2,l3")->select()->toArray();
                $profits = [];
                // 商品自设
                if ($commodity['is_base_distribution'] == 1) {
                    $goodsGrades = json_decode($commodity['distribution'], true);
                    array_push($agents, ['id' => 0]);
                    foreach ($agents as $ak => $av) {
                        $des = $this->getCommodityGrade($goodsGrades, $av['id'], $distribution['level']);
                        if (count($des) > 0) {
                            array_push($profits, $des);
                        }
                    }

                }
                // 系统默认
                if ($commodity['is_base_distribution'] == 0) {
                    $arr = ['id' => 0];
                    $keyword = [1 => 'first', 2 => 'second', 3 => 'third'];
                    foreach ($keyword as $key => $value) {
                        $figure = $distribution['profit'][$value];
                        $arr['l'.$key] = $figure;
                    }
                    array_push($agents, $arr);
                    foreach ($agents as $ak => $av) {
                        $arr = [];
                        for ($i = 1; $i <= $distribution['level']; $i++) {
                            array_push($arr, ['type' => 0, 'figure' => $av['l'.$i]]);
                        }
                        array_push($profits, $arr);
                        unset($arr);
                    }
                }
                $return = [];
                foreach ($profits as $pk => $pvs) {
                    foreach ($pvs as $vk => $vv) {
                        foreach ($prices as $prk => $prv) {
                            // 1固定
                            if ($vv['type'] == 1) {
                                array_push($return, $vv['figure']);
                            }
                            // 0比例
                            if ($vv['type'] == 0) {
                                array_push($return, round($prv*$vv['figure']/100, 2));
                            }
                        }
                    }
                }
            }
        } else {
            return [HTTP_SUCCESS, "没开分销"];
        }
        return [HTTP_SUCCESS, getRangeArr($return)];
    }

    /**
     * 获取商品的所有价格
     * @param $commodity_id
     * @param $sell_price
     * @param $has_sku
     * @return array
     * @throws
     */
    private function getPrices($commodity_id, $sell_price, $has_sku)
    {
        $prices = [$sell_price];
        $level_price = [[$sell_price, json_decode(Commodity::where('id', $commodity_id)->value('level_price'), true)]];
        if ($has_sku == 1) {
            $prices = [];
            $level_price = [];
            $sku = Sku::with('SkuInventory')->where('commodity_id', $commodity_id)->select();
            foreach ($sku as $k => $v) {
                array_push($prices, $v['SkuInventory']['sell_price']);
                array_push($level_price, [$v['SkuInventory']['sell_price'], json_decode($v['SkuInventory']['level_price'], true)]);
            }
        }
        $config = json_decode(Configuration::where('type', 'memberLevel')->value('configuration'), true);
        if ($level_price[0][1]['type'] > 0 && $this->user['level'] > 0 && $config['is_open'] == 1) {
            $member_prices = [];
            // 根据会员等级
            if ($level_price[0][1]['type'] == 1) {
                foreach ($level_price as $key => $value) {
                    $price = $value[0];
                    foreach ($value[1]['price'] as $vk => $vv) {
                        if ($vv['level'] == $this->user['level']) {
                            // 价格
                            if ($vv['type'] == 1) {
                                array_push($member_prices, $vv['price']);
                            }
                            // 折扣
                            if ($vv['type'] == 2) {
                                array_push($member_prices, round($price * $vv['price'] / 10, 2));
                            }
                        }
                    }
                }
            }
            // 系统默认
            if ($level_price[0][1]['type'] == 2) {
                $level = MembershipLevel::where('level', $this->user['level'])->find();
                foreach ($prices as $key => $price) {
                    array_push($member_prices, round($price * $level['discount'] / 10, 2));
                }
            }
            $prices = $member_prices;
        }
        $group = Commodity::isGroup($commodity_id);
        if ($group[0]) {
            $prices = [];
            if (isset($group[0]['sku'])) {
                foreach ($group[0]['sku'] as $k => $v) {
                    $prices = is_numeric($v['activity_price']) ? array_merge($prices, [$v['activity_price']]) :
                        array_merge($prices, json_decode($v['activity_price'], true));
                }
            } else {
                $prices = is_numeric($group[0]['activity_price']) ? array_merge($prices, [$group[0]['activity_price']]) :
                    array_merge($prices, json_decode($group[0]['activity_price'], true));
            }
            if ($group[0]['use_single'] == 1) {
                array_push($prices, $sell_price);
            }
        }
        $sckill = Commodity::isSeckill($commodity_id);
        if ($sckill) {
            $prices = [];
            if ($sckill['has_sku'] == 1) {
                foreach ($sckill['sku'] as $k => $v) {
                    $prices = array_merge($prices, [$v['activity_price']]);
                }
            } else {
                $prices = [$sckill['activity_price']];
            }
        }
        $presell = Commodity::isPresell($commodity_id);
        if ($presell) {
            $prices = [];
            if ($presell['has_sku'] == 1) {
                foreach ($presell['sku'] as $k => $v) {
                    $prices = array_merge($prices, [$v['activity_price']]);
                }
            } else {
                $prices = [$presell['activity_price']];
            }
        }
        return array_unique($prices);
    }

    /**
     * 商品自设的等级分销
     * @param $grades
     * @param $grade_id
     * @param $level
     * @return array
     */
    private function getCommodityGrade($goodsGrades, $grade_id, $level)
    {
        $grade = [];
        $arr = [];
        // 新数据
        if (isset($goodsGrades[0][0][0])) {
            foreach ($goodsGrades as $key => $value) {
                if ($value[0][0] == $grade_id) {
                    $grade = $value[1];
                }
            }
        } else {
            if ($grade_id == 0) {
                $grade = $goodsGrades;
            }
        }
        if (count($grade) > 0) {
            $grade = $this->sort($grade);
            for ($i = 1; $i <= $level; $i++) {
                // type,0比例 1固定
                $arr[$i] = $grade[$i];
            }
        }
        return $arr;
    }
}